#! /usr/bin/env python
# coding=utf-8
# ******************************************************************************
# licensed under the Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#     http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
# PURPOSE.
# See the Mulan PSL v2 for more details.
# Author: Lostway
# Create: 2020-08-19
# ******************************************************************************/
"""
download rpm from fedora and import these to obs
"""
import os
import subprocess
import time

import requests
import bs4
from autoimport.logmodule import logger

pre = "https://kojipkgs.fedoraproject.org//packages/"
LOGGER = logger.init('fedora_project')
CURRENT_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


def procees_data(file, obs, arch):
    """
    处理输入数据
    Returns:
        pkg_list  软件包列表
        obs  obs本地仓库地址
        arch  寻找软件包的最低架构版本，默认为31。将往上最高寻找2个版本
    """
    # file = ""
    # obs = ""
    # try:
    #     file = sys.argv[1]
    #     obs = sys.argv[2]
    # except IndexError:
    #     LOGGER.error("Need to add the input txt.")
    #     exit()

    # try:
    #     arch = int(sys.argv[3])
    # except IndexError:
    #     arch = 31

    pkg_list = []
    with open(file) as f:
        for s in f:
            pkg_list.append(s.rstrip("\n"))
    return pkg_list, obs, arch


def get_download_url(name, arch_version):
    """
    获取单个软件包下载地址
    Args:
        name: 软件包名
        arch_version: 软件包适用的架构的版本

    Returns:
        download_url  软件包的下载地址
    """
    LOGGER.info("Processing %s" % name)

    # order_str 为此网页的url后缀，将软件包按修改顺序排列
    order_str = '?C=M;O=A'

    url_name = pre + name + "/" + order_str + '/'
    response_name = request_get(url_name)

    soup_name = bs4.BeautifulSoup(response_name.text, 'html.parser')

    # 获取网站最后一个链接地址，为软件包最新版本
    version = soup_name.find_all("a")[-1].get_text()
    url_version = pre + name + "/" + version

    response_version = request_get(url_version + order_str)
    soup_version = bs4.BeautifulSoup(response_version.text, 'html.parser')
    fc_version_list = soup_version.find_all("a")

    # 寻找所需版本的架构的软件包，默认fedora31。若找不到，则向上最多寻找两个版本。
    tmp_version = ""
    release_list = []
    for i in range(3):
        tmp_version = 'fc' + str(arch_version + i) + "/"
        for fc_v in fc_version_list:
            fc_v_text = fc_v.get_text()
            if fc_v_text.endswith(tmp_version):
                release_list.append(int(fc_v_text.split(".")[0]))
        if release_list:
            break

    # 此最新版本的软件包不支持所需要的版本的架构
    if not release_list:
        LOGGER.error("No available version")
        LOGGER.error('*' * 70)
        return

    release_num = sorted(release_list)[-1]
    url_full = url_version + str(release_num) + '.' + tmp_version + "src/"

    response_full = request_get(url_full)
    soup_full = bs4.BeautifulSoup(response_full.text, 'html.parser')

    # 获取到网页最后一个链接地址，即为下载地址
    fc_full = soup_full.find_all("a")[-1].get_text()

    LOGGER.info("Pakcage's full name is " + fc_full)

    download_url = url_full + fc_full
    LOGGER.info("*" * 70)
    return download_url


def request_get(url):
    """
    访问网页
    Args:
        url: 访问网页的地址

    Returns:
        response: 网页response内容
    """
    try:
        t1 = time.time()
        response = requests.get(url, timeout=10)
        t2 = time.time()
    except requests.Timeout as e:
        LOGGER.error('Request timed out：' + str(e.response))
        raise TimeoutError('Request timed out：' + str(e.response))
    except requests.HTTPError as e:
        LOGGER.error('http request wrong:' + str(e.response))
        raise requests.HTTPError('http request wrong:' + str(e.response))
    else:
        # 通过status_code判断请求结果是否正确
        LOGGER.info('Request takes %s seconds' % (t2 - t1))
        if response.status_code == 200:
            LOGGER.info('Connect successfully: 200')
            return response
        elif response.status_code == 404:
            LOGGER.error('Connection failed：' +
                         str(response.status_code) + ',' + str(response.reason))
            raise RuntimeError("No package found!")
        else:
            LOGGER.error('Connection failed：' +
                         str(response.status_code) + ',' + str(response.reason))
            raise RuntimeError("Internal sever error!")


def download_url_list(pkg_list, arch):
    """
    批量获取软件包下载地址，并将成功及失败结果存储到txt
    Args:
        pkg_list:
        arch:

    Returns:
    """
    success_list = []
    fail_list = []
    for pkg in pkg_list:
        try:
            full_url = get_download_url(pkg, arch)
            if full_url:
                success_list.append(full_url)
            else:
                fail_list.append(pkg)
        except requests.Timeout as e:
            fail_list.append(pkg)
            LOGGER.info(e.response)
            LOGGER.info('*' * 70)
        except RuntimeError as e:
            fail_list.append(pkg)
            LOGGER.info(e)
            LOGGER.info('*' * 70)
        except Exception as e:
            fail_list.append(pkg)
            LOGGER.info(e)
            LOGGER.info('*' * 70)

    with open(os.path.join(CURRENT_PATH, "downloadsrcrpm/url.txt"), "w") as f:
        for url in success_list:
            f.write(url + '\n')

    with open(os.path.join(CURRENT_PATH, "Logs/download_fedora_src/FailedPackage.txt"), "w") as f:
        for pkg in fail_list:
            f.write(pkg + '\n')

    LOGGER.info("%d packages' url are fetched. Failed %d packages" %
                (len(success_list), len(fail_list)))

    if fail_list:
        for p in fail_list:
            LOGGER.error(p + "download fail")


def remove_blank(src_str):
    """
    remove blank
    Args:
        src_str: source string

    Returns: updated string

    """
    return src_str.replace("\n", "").replace("\r", "")


def import_srcrpm(obs_location):
    """
    import source rpm
    Args:
        obs_location:  local osc path

    Returns: NONE

    """
    # 通过获取到的源码包url，将源码包下载、解压、上传到OBS中进行编译
    os.system("mkdir ./rpm_download_tmp")
    with open(CURRENT_PATH + "/downloadsrcrpm/url.txt", "r") as f:
        urls_temp = f.read()
        urls = urls_temp.splitlines()

        for url in urls:
            os.system("rm -rf ./rpm_download_tmp/*")
            # 下载源码包到指定路径
            LOGGER.info("Downloading src_rpm by {}".format(url))
            commond_wget = "wget -P ./rpm_download_tmp {} >/dev/null 2>&1".format(
                url)
            download_result = os.system(commond_wget)
            if download_result != 0:
                LOGGER.error("Download failed")
                continue
            else:
                LOGGER.info("Download success")

            # 上传源码包到OBS
            src_rpm_list = os.listdir("rpm_download_tmp")
            for src_rpm in src_rpm_list:
                LOGGER.info("Loading import {} to obs".format(src_rpm))
                command_import = "osc importsrcpkg {} -p {} -c".format(
                    "./rpm_download_tmp/*", obs_location)
                import_result = subprocess.run(command_import, shell=True, stdout=subprocess.PIPE,
                                               stderr=subprocess.PIPE,
                                               encoding="utf-8")
                if import_result.returncode == 0:
                    LOGGER.info("Import {} success".format(src_rpm))
                    with open(os.path.join(CURRENT_PATH, "downloadsrcrpm/success.txt"), "a") as f:
                        f.write(src_rpm + '\n')
                else:
                    LOGGER.error(
                        "Import {} failed, reason: {}".format(src_rpm, import_result.stderr))
                    with open(os.path.join(CURRENT_PATH, "Logs/download_fedora_src/FailedPackage.txt"), "a") as f:
                        f.write(src_rpm + '\n')
            os.system("rm -rf ./rpm_download_tmp/*")
            LOGGER.info('*' * 70)
    os.system("rm -rf rpm_download_tmp")


def main(rpm_list_file, obs_path, fedora_version=31):
    """
    main
    Args:
        rpm_list_file: need import rpm list file
        obs_path:  osc path
        fedora_version: rpm fedora version

    Returns: NONE

    """
    logger.add_file_handler(LOGGER, "download_fedora_src", "fedora_download")
    time_start = time.time()
    pkg_list, obs_location, arch = procees_data(
        rpm_list_file, obs_path, fedora_version)
    download_url_list(pkg_list, arch)
    time_end = time.time()
    t = time_end - time_start
    LOGGER.info("Takes %s seconds totally" % t)
    LOGGER.info("Done!")
    LOGGER.info('#' * 70)
    import_srcrpm(obs_location)
    with open(os.path.join(CURRENT_PATH, "Logs/download_fedora_src/FailedPackage.txt"), "r") as f:
        return f.read()

# if __name__ == "__main__":
#     main()
